<template>
    <div class="wrap">
        <!--标准-->
        <div class="dialog-row mt3">
            <span class="text-ellipsis"> {{ $t('message.FastenerDesign.Standard') }} : </span>
            <el-select class="flex-grow-1"
                       v-model="curStandard"
                       :title="curStandard">
                <el-option v-for="(item,index) in standardList" :key="index" :value="item">
                    {{ item }}
                </el-option>
            </el-select>
        </div>
        <!--类别-->
        <div class="dialog-row mt3 ">
        <span class="text-ellipsis"
              :title="$t('message.SupportDesign.class')">
          {{ $t('message.SupportDesign.class') }}：
        </span>
            <el-select class="flex-grow-1"
                       v-model="curClass"
                       :title="curClass">
                <el-option v-for="(item,index) in typeList" :key="index" :value="item">{{ item }}</el-option>
            </el-select>
        </div>

        <!--分类-->
        <div class="dialog-row mt3">
        <span class="text-ellipsis"
              :title="$t('message.SupportDesign.type')">
              {{ $t('message.SupportDesign.type') }}：
        </span>
            <el-select class="flex-grow-1"
                       v-model="curComponent"
                       :title="curComponent"
                       @change="changeVal">
                <el-option v-for="(item,index) in componentList" :key="index" :value="item.name">{{ item.name }}
                </el-option>
            </el-select>
        </div>

        <!--零件参数-->
        <div v-if="primaryAttribute">
            <div class="dialog-row mt3">
          <span class="text-ellipsis"
                :title="getPrimaryAttributeAlias">
            {{ getPrimaryAttributeAlias }}：
          </span>
                <el-select class="flex-grow-1"
                           v-model="selected.primary"
                           :title="selected.primary"
                           @change="changeSelectEventHandler('primary')">
                    <el-option v-for="(op,index) in primaryAttribute.options" :key="index" :value="op">{{
                        op
                        }}
                    </el-option>
                </el-select>
            </div>
            <div class="dialog-row mt3" v-for="(attribute,index) in attributes" :key="index">
          <span class="text-ellipsis"
                :title="attribute.alias">
            {{ attribute.alias }}：
          </span>
                <el-select v-if="!attribute.isInput" class="flex-grow-1"
                           v-model="selected[attribute.key]"
                           :title="selected[attributes.key]"
                           @change="changeSelectEventHandler(attribute.key)">
                    <el-option v-for="(option,index) in getAttributeOptions(attribute.key)" :key="index"
                               :value="option">
                        {{ option }}
                    </el-option>
                </el-select>
                <div v-else class="flex-grow-1">
                    <el-input-number :max="getMaxValue(attribute)" :step="1" :min="getMinValue(attribute)"
                                     v-model="selected[attribute.key]"/>
                    <p class="attribute-unit">{{ attribute.unit }}</p>
                </div>
            </div>
        </div>

        <!--缩略图-->
        <div class="thumbnail">
            <img v-if="partInfo" class="thumbnail-img" :src="partInfo.specImage"/>
        </div>

        <!--旋转轴-->
        <div>
            <el-label class="el-form-item__label">{{ $t('message.SupportDesign.rotateAxis') }}：</el-label>
            <el-radio v-model="params.rotateAxis" :label="'x'" @change="changeVal">
                {{ $t('message.SupportDesign.xAxis') }}
            </el-radio>
            <el-radio v-model="params.rotateAxis" :label="'y'" @change="changeVal">
                {{ $t('message.SupportDesign.yAxis') }}
            </el-radio>
            <el-radio v-model="params.rotateAxis" :label="'z'" @change="changeVal">
                {{ $t('message.SupportDesign.zAxis') }}
            </el-radio>
        </div>
        <!--角度-->
        <div class="dialog-row mt-1">
            <el-label :style="'margin:2px; flex:none;'">{{ ($t('message.SupportDesign.angle')) }}：</el-label>
            <base-input-number v-model="params.angle"
                               @change="changeVal"/>
        </div>

        <!--按钮组-->
        <div class="btn">
            <!--            <el-button type="primary" @click="confirm" >{{ $t('message.Common.confirm') }}</el-button>-->
            <el-button @click="close">{{ $t('message.Common.close') }}</el-button>
        </div>
    </div>

</template>

<script>
import {supportDesignCommand} from "../../Command/SupportDesignCommand";
import {Vector3} from "three";
import DialogMixin from "./DialogMixin";

export default {
    mixins: [DialogMixin],
    name: "SupportDesign",
    data() {
        return {
            standardList: [],
            categoryList: [],
            typeList: [],
            componentList: [],
            curStandard: null,
            curClass: null,
            curPosition: null,
            curComponent: null,
            partInfo: null,
            primaryAttribute: null,
            attributes: {},
            selected: {
                primary: ''
            },
            optionsValue: {},
            levelNames: [],
            levelInfo: [],
            params: {
                position: [],
                //direction: [],
                queryListActiveMap: {
                    direction: 1,
                    position: 0,
                },
                angle: 0,
                rotateAxis: 'x',
            },

            needSendPreviewCmd: false, //是否需要给内核发送预览命令
            hasPreviewed: false,//是否已经执行预览
        }
    },
    created() {
    },
    mounted() {
        supportDesignCommand.init(500, 300, 500, () => {
            this.init();
            this.changePluginContainerHeight();
            //注册鼠标移动事件
            supportDesignCommand.handleMovePick((posInfo) => {
                this.params.position.length = 0;
                this.params.position.push(posInfo);
                this.handlePick(true);
                this.needSendPreviewCmd = false;
                this.hasPreviewed = true; //鼠标移动预览后置为true
            });
            //注册鼠标按下事件
            supportDesignCommand.handleDownPick((posInfo) => {
                if (this.hasPreviewed) { //只有执行完预览后才能确定
                    this.params.position.length = 0;
                    this.params.position.push(posInfo);
                    this.handlePick(false);
                    //考虑到角度属性可能发生了变化，新一轮开始，需要发送脚本
                    this.needSendPreviewCmd = true;
                }
            })
        });
    },
    watch: {
        curStandard() {
            this.getTypeListByStd();
        },
        curClass() {
            this.getComponentList();
        },
        curComponent() {
            this.getComponentData();
            this.needSendPreviewCmd = true;
            this.changeVal();
        },
        'partInfo': {
            handler(newValue) {
                if (!newValue) {
                    return;
                }
                this.attributes = {};
                this.parsePartInfo(newValue);
                // 解析材质信息
                this.parseComponentMaterialInfo();
            },
            immediate: true,
        },
    },
    computed: {
        getPrimaryAttributeAlias() {
            return this.primaryAttribute?.alias ?? "";
        }
    },
    methods: {
        //调整高度
        changePluginContainerHeight() {
            supportDesignCommand.changePluginContainerHeight(
                {minWidth: this.$el.clientWidth, maxHeight: this.$el.clientHeight + 10})
        },
        //初始化
        init() {
            this.params.queryListActiveMap.direction = 0;
            this.params.queryListActiveMap.position = 1;
            this.primaryAttribute = null;
            this.attributes = {};
            //获取支架库的标准数据
            let params = {
                url: '/stdlib/standard/'
            }
            supportDesignCommand.getSupportData(params, data => {
                if (data && data.code === 200) {
                    this.standardList.length = 0;
                    data.data?.forEach(e => this.standardList.push(e));
                    this.curStandard = this.standardList[0];
                } else {
                    supportDesignCommand.eventBusAlertMsg('未获取到标准库数据，请联系管理员维护！', 'warning');
                }
            })
        },
        //根据当前标准获取类型列表
        getTypeListByStd() {
            if (this.curStandard != null) {
                let formData = new Map();
                formData.set("standardName", this.curStandard);
                formData.set("categoryName", '支架');
                let params = {
                    url: '/stdlib/getClassNamesByEntering/',
                    data: formData,
                    isPost: true,
                }
                supportDesignCommand.getSupportData(params, data => {
                    if (data && data.code === 200) {
                        this.typeList.length = 0;
                        data.data?.forEach(e => this.typeList.push(e));
                        if (this.curClass === this.typeList[0]) {
                            this.curClass = this.typeList[1]
                        } else {
                            this.curClass = this.typeList[0]
                        }
                    } else {
                        supportDesignCommand.eventBusAlertMsg('未获取到标准库数据，请联系管理员维护！', 'warning');
                    }
                })
            }
        },
        //根据当前标准获取对应的零件列表
        getComponentList() {
            let url = '/stdlib/getComponentNamesByEntering';
            let formData = new Map();
            formData.set("standardName", this.curStandard);
            formData.set("categoryName", '支架');
            formData.set("clsName", this.curClass);
            let params = {
                url: url,
                data: formData,
                isPost: true,
            }
            supportDesignCommand.getSupportData(params, data => {
                console.log(data)
                if (data && data.code === 200) {
                    this.componentList.length = 0;
                    let compArr = data.data?.filter(comp => comp.componentStatus === 'Approved'); //增加过滤已审批通过的状态 20241230
                    compArr.forEach(e => this.componentList.push(e));
                    this.curComponent = this.componentList[0];
                    if (this.curComponent === this.componentList[0]) {

                    }
                } else {
                    supportDesignCommand.eventBusAlertMsg('未获取到标准库数据，请联系管理员维护！', 'warning');
                }
            })
        },
        //获取零件的相关信息
        getComponentData() {
            let url = '/stdlib/getPartInfoByComponentName';
            let baseComponentParam = {
                standardName: this.curStandard,
                categoryName: '支架',
                className: this.curClass,
                componentName: this.curComponent?.name,
            }
            let params = {
                url: url,
                data: baseComponentParam,
                isFormData: false,
                isPost: true,
            }
            supportDesignCommand.getSupportData(params, partInfo => {
                if (partInfo && partInfo.code === 200) {
                    this.partInfo = partInfo.data;
                } else {
                    supportDesignCommand.eventBusAlertMsg('未获取到标准库数据，请联系管理员维护！', 'warning');
                }
            })
        },
        //关闭
        close() {
            supportDesignCommand.closeActiveCmd();
        },
        //组织发送命令时的数据
        getCommandParams(isPreview = false) {
            if (!this.params.position || this.params.position.length === 0 || !this.curComponent) {
                return;
            }
            return {
                isPreview: isPreview,
                standardName: this.curStandard,
                category: '支架',
                class: this.curClass,
                component: this.curComponent.name,
                optionsValue: this.optionsValue,
                materialInfo: this.getMaterialInfo(),
                position: new Vector3(this.params.position[0].x, this.params.position[0].y, this.params.position[0].z),
                angle: this.params.angle,
                rotateAxis: this.params.rotateAxis,
                needSendPreviewCmd: this.needSendPreviewCmd,
            }
        },
        switchQuery(name) {
            for (const key in this.params.queryListActiveMap) {
                if (key === name) {
                    this.params.queryListActiveMap[key] = 1;
                } else {
                    this.params.queryListActiveMap[key] = 0;
                }
            }
        },
        //获取材质信息
        getMaterialInfo() {
            let result = {};
            this.levelInfo?.forEach(level => {
                if (level.name === "材质") {
                    result["材质"] = level.value;
                    result["materialId"] = "";
                } else if (level.name === "性能等级") {
                    result["性能等级"] = level.value;
                }
            })
            if (!result["材质"] || result["材质"] === "") {
                result["材质"] = "";
                result["materialId"] = "";
            }
            return result;
        },
        //预览/生成
        handlePick(isPreview) {
            let paramInfo = this.getCommandParams(isPreview);
            if (paramInfo) {
                supportDesignCommand.createSupport(paramInfo);
            }
            //如果此时是非预览状态，执行完确定后还原状态
            if (!isPreview) {
                this.hasPreviewed = false;
            }
        },
        //值改变事件
        changeVal(oldVal, newVal) {
            if (this.params && this.params.position.length > 0) {
                if (this.needSendPreviewCmd) {
                    this.handlePick(true);
                } else {  //无需发送预览，但判断UI面板控件值是否发生改变，变了需要发
                    this.needSendPreviewCmd = oldVal !== newVal;
                    this.handlePick(true);
                }
            } else {
                //首次打开 UI，此时鼠标没有移动，故没有位置：不需要预览，但需设置下一次的属性
                this.needSendPreviewCmd = true;
            }
        },
        //零件参数改变事件
        changeSelectEventHandler(key) {
            if (key === "primary") {
                this.updateAttributeValue(this.selected[key]);
            }
            // 把选中的信息传递给属性组件
            this.update();
            this.needSendPreviewCmd = true;  //零件规格参数发生变化需要重新发送脚本
            this.handlePick(true);
        },
        //更新属性值
        updateAttributeValue(primaryValue) {
            // 更新属性值
            // 通常是由于主属性变更会触发该函数
            let attrKeys = Object.keys(this.attributes);
            attrKeys.forEach(key => {
                let attribute = this.attributes[key];

                let attrNewValue;
                attribute.options.some(option => {
                    if (option.primary === primaryValue) {
                        // 选中该属性对应的主属性的第一个选项
                        attrNewValue = option.options[0];
                        return true;
                    }
                    return false;
                })

                // 如果属性是一个范围
                if (attribute.isInput) {
                    this.selected[attribute.key] = this.parseRangeValue(attrNewValue, false);
                } else {
                    this.selected[attribute.key] = attrNewValue;
                }
            });
        },
        //更新 把选中的信息传递给属性组件
        update() {
            this.optionsValue = {};
            this.optionsValue[this.primaryAttribute.alias] = this.selected.primary;

            // 遍历attribute列表拿到所有的属性的别名及对应的值，构建OptionValue
            Object.keys(this.attributes).forEach(attrKey => {
                this.optionsValue[this.attributes[attrKey].alias] = this.selected[attrKey];
            });
        },
        //获取属性对应的参数值列表
        getAttributeOptions(key) {
            let index = this.attributes[key].options.findIndex(o => o.primary === this.selected.primary);
            if (index !== -1) {
                return this.attributes[key].options[index].options;
            } else {
                return [];
            }
        },
        //获取属性区间
        getAttributeRange(attribute) {
            // 获取当前选中的属性的索引值
            let targetIndex = attribute.options.findIndex(option => {
                return option.primary === this.selected.primary;
            });
            // 如果是一个区间，则这个属性的option有且只有一个，故取第一项的value
            let range = attribute.options[targetIndex].options[0];
            return range;
        },
        //获取属性区间值
        parseRangeValue(range, isMax) {
            let regx = /(?<min>^\d*)~(?<max>\d*)$/;
            let group = range.match(regx).groups;
            return isMax ? group.max : group.min;
        },
        //获取最大值
        getMaxValue(attribute) {
            let range = this.getAttributeRange(attribute);
            return this.parseRangeValue(range, true);
        },
        //获取最小值
        getMinValue(attribute) {
            let range = this.getAttributeRange(attribute);
            return this.parseRangeValue(range, false);
        },
        //解析零件属性
        parsePartInfo(partInfo) {
            if (partInfo) {
                this.clearData();
                // 先解析其他属性 后面需要动态设置其他属性的值，所以必须保证在解析主属性之前其他属性是不能为空
                this.parserAttributes(partInfo);
                this.parserPrimaryAttribute(partInfo);
                // todo 先设置为第一个主属性
                if (this.primaryAttribute) {
                    this.selected.primary = this.primaryAttribute.options[0];
                    this.changeSelectEventHandler("primary");
                }
            }
        },
        //清除数据
        clearData() {
            this.params.angle = 0;
            this.params.position.splice(0);
            //this.switchQuery("position");
            supportDesignCommand.clearPreview();
        },
        //解析零件属性值
        parserAttributes(partInfo) {
            // 解析其他的属性值
            if (partInfo.secondaryAttributes && partInfo.columnAlias) {
                let keys = Object.keys(partInfo.columnAlias);
                let values = Object.values(partInfo.columnAlias);

                values.forEach((v, index) => {
                    // 如果值等于主属性
                    if (v === partInfo.primaryAttributeName) {
                        return;
                    }

                    let attribute = {};
                    let key = keys[index];
                    attribute['key'] = key;
                    attribute['alias'] = v;
                    attribute['options'] = [];

                    partInfo.secondaryAttributes.forEach(s => {
                        // 去其他属性列表匹配对应的选项
                        let targetAttribute = null;
                        s.attributes.some(a => {
                            for (let i = 0; i < a.length; i++) {
                                if (a[i].name === v) {
                                    targetAttribute = a[i];
                                    return true;
                                }
                            }
                            return false;
                        });
                        if (targetAttribute) {
                            attribute['isInput'] = targetAttribute?.isInput;
                            attribute['unit'] = targetAttribute?.unit;

                            attribute.options.push({
                                primary: s.primaryAttributeValue,
                                options: targetAttribute.values
                            })
                        }
                    });
                    this.attributes[key] = attribute;
                    this.$set(this.selected, key, "");
                })

            } else {
                //throw new Error("解析其他属性时出错");
                //没有额外属性的  不处理
            }
        },
        //解析主要属性值
        parserPrimaryAttribute(partInfo) {
            let primaryAttribute = {};
            if (partInfo.primaryAttributeName && partInfo.columnAlias) {
                let keys = Object.keys(partInfo.columnAlias);
                let values = Object.values(partInfo.columnAlias);

                let targetIndex = values.indexOf(partInfo.primaryAttributeName);
                if (targetIndex !== -1) {
                    let primaryAttributeKey = keys[targetIndex];
                    primaryAttribute['alias'] = partInfo.primaryAttributeName;
                    primaryAttribute['key'] = primaryAttributeKey;
                    primaryAttribute['options'] = partInfo.secondaryAttributes.map(s => s.primaryAttributeValue);

                    this.primaryAttribute = primaryAttribute;
                    return;
                }
            } else {
                //throw new Error("解析标准件主属性时出错");

                //尚未配置自定义变量 不处理
            }

        },
        //解析材质信息
        parseComponentMaterialInfo() {
            this.levelInfo = [];
            if (!this.partInfo || !this.partInfo.materialInfo) {
                return;
            }

            let materialInfo = this.partInfo.materialInfo;
            let levelNames = Object.values(materialInfo.levelName);
            let curLevel = materialInfo.rootLevel;

            this.levelNames = levelNames;

            let startIndex = 0;
            if (this.equalPrimaryAttribute(levelNames[0])) {
                curLevel = this.getNextLevel(curLevel, Object.values(this.optionsValue));
                startIndex++;
            }

            // 解析等级规则数
            this.parseLevelTree(startIndex, curLevel);
        },
        // 解析等级规则数
        parseLevelTree(startIndex, curLevel) {
            // 匹配等级规则
            for (let i = startIndex; i < this.levelNames.length; i++) {
                let levelInfo = {
                    name: this.levelNames[i],
                    value: this.getCurLevelValue(curLevel),
                    options: this.getLevelOptions(curLevel),
                    nextLevelName: this.getNextLevelName(i),
                    level: curLevel,
                    isMaterial: this.levelNames[i] === "材质",
                };
                this.levelInfo.push(levelInfo);

                // 移动到下一级
                curLevel = this.getNextLevel(curLevel, this.getCurLevelValue(curLevel));
            }
        },
        //判断是否是同一个属性
        equalPrimaryAttribute(attrKey) {
            let aliasName = this.findAttributeAlias(attrKey);
            return aliasName === this.partInfo?.primaryAttributeName;
        },
        //获取下一等级
        getNextLevel(curLevel, curLevelValue) {
            if (!curLevel) {
                return;
            }

            let nextLevel = null;
            // 获取下一级等级规则
            curLevel.some(level => {
                if (level.levelValue === curLevelValue) {
                    nextLevel = level;
                    return true;
                }
                return false;
            });

            return nextLevel?.nextLevel;
        },
    },
    destroyed() {
    },
}
</script>

<style scoped>
.wrap {
    font-size: 12px;
}

.dialog-row {
    margin: 7px 0;
    display: flex;
    height: 26px;
    align-items: center;
}

.thumbnail-img {
    width: 100%;
    height: auto;
    border: 1px solid var(--border-color1);
    @apply tw-h-full;
}

.dialog-variable-input {
    display: flex;
    align-items: center;
    flex: 1;
    position: relative;
    height: 24px;
}
</style>
